﻿#include <QStyleOptionGraphicsItem>
#include <QGraphicsView>

#include "ImageItem.h"
#include "JistCommonModel.h"
#include "JistAniTool.h"

int X2 = (960/4 * 1.5);
// 효과 적용 + 회전시 테두리부분이 표시되지 않음
// 임시로 2배의 영역부부까지 대응
int gModScale = 2;

ImageItem::ImageItem(int imgId, int spriteId, QVector< QList < JistCommonData> > *spriteData, int oX, int oY )
    :m_SpriteData(*spriteData)
    ,m_SrcImage(0)
    ,m_bEffDraw(true)
    ,m_Scale(1.0)
    ,m_Angle(0)
    ,m_ScaleXY(1,1)
    ,m_TextItem(0)
    ,m_iAnchor(0)
{
    m_iImageId = imgId;
    m_iSpriteId = spriteId;

    // 이미지나 스프라이트가 삭제된 후  참조되는 경우제외
    if((0 <= m_iSpriteId && 0 <= m_iImageId) && m_iImageId < m_SpriteData.count() && m_iSpriteId < m_SpriteData[m_iImageId].count()){
        m_SrcImage = &m_SpriteData[imgId][spriteId].m_img;
        m_Image = *m_SrcImage;
    }
    // 빈 셀
    else{//(0 > m_iSpriteId || 0 > m_iImageId)
        m_Image = g_EmptyImage;
        m_SrcImage = &m_Image;
    }
    //QGraphicsRectItem::QGraphicsRectItem();
    // 회전시 중앙
    //setTransformOriginPoint(m_Image.width()/2, m_Image.height()/2);
    m_composition_mode = QPainter::CompositionMode_Source;
    m_FlipH = 0;
    m_FlipV = 0;
QSize tempSize = m_Image.size();
qreal wr = m_Image.size().width();
qreal r1 = wr / m_Image.size().height();
qreal r2 = m_Image.size().height() / wr;
// 이미지가 널일때 호출스택이 여길 가리킴
    m_Modscale =  std::max(m_Image.size().width() / m_Image.size().height(), m_Image.size().height() / m_Image.size().width());

    if(m_ResultImage.isNull())
        m_ResultImage = QImage(m_Image.size() * m_Modscale, QImage::Format_ARGB32);
    m_ResultImage.fill(0);

    setOriginPosInit(oX, oY);
}
// 참조 이미지 초기화
void ImageItem::init()
{
    if((0 <= m_iSpriteId && 0 <= m_iImageId) && m_iImageId < m_SpriteData.count() && m_iSpriteId < m_SpriteData[m_iImageId].count()){
        m_SrcImage = &m_SpriteData[m_iImageId][m_iSpriteId].m_img;
        m_Image = m_SrcImage->mirrored(m_FlipH, m_FlipV);
    }
    else{
        m_Image = g_EmptyImage;
        m_SrcImage = &m_Image;
    }

    if(m_ResultImage.isNull())
        m_ResultImage = QImage(m_Image.size() * m_Modscale, QImage::Format_ARGB32);
    m_ResultImage.fill(0);
    setRect(-m_ResultImage.width()/2, -m_ResultImage.height()/2, m_ResultImage.width(), m_ResultImage.height());

    //setTransformOriginPoint(0, 0);
}

void ImageItem::setOriginPos(int index_X, int index_Y)
{
    int posX[3] = { X1, X2, X3};
    int posY[3] = { Y1, Y2, Y3};
    setPos(x() - m_OriginPos.x(), y() - m_OriginPos.y());
    QPointF p = pos();
    m_OriginPos = QPoint(posX[index_X], posY[index_Y]);
    setPos(x() + m_OriginPos.x(), y() + m_OriginPos.y());
    QPointF p2 = pos();
    m_oIndex_X =  index_X;
    m_oIndex_Y =  index_Y;
}

void ImageItem::setPosInit()
{
    int posX[3] = { X1, X2, X3};
    int posY[3] = { Y1, Y2, Y3};
    m_OriginPos = QPoint(posX[m_oIndex_X], posY[m_oIndex_Y]);
}

void ImageItem::setOriginPosInit(int index_X, int index_Y)
{
    m_oIndex_X =  index_X;
    m_oIndex_Y =  index_Y;
    setPosInit();
    setPos(m_OriginPos.x() + m_RelativePos.x(), m_OriginPos.y() + m_RelativePos.y());
}

void ImageItem::setOriginPosInit()
{
    setPosInit();
    setPos(m_OriginPos.x() + m_RelativePos.x(), m_OriginPos.y() + m_RelativePos.y());
}


void ImageItem::setRelativePos()
{
    setPosInit();
    m_RelativePos = QPoint(pos().x() - m_OriginPos.x(), pos().y() - m_OriginPos.y());
}

QPoint ImageItem::getRelativePos()
{
    return m_RelativePos;
}

void ImageItem::setPos(const QPointF & pos)
{
    QGraphicsItem::setPos(pos);
    setRelativePos();

}
void ImageItem::setPos(qreal ax, qreal ay)
{
    setPos(QPointF(ax, ay));
    update();
}

void ImageItem::setScale(qreal factor)
{
//    //QSize s = m_Image.size();
//    //QSize sc = m_Image.size() * factor;
//    m_Scale = factor;
//    m_ResultImage = QImage(m_Image.size() * factor * m_Modscale, QImage::Format_ARGB32);


//    //setTransformOriginPoint(-m_ResultImage.rect().width()/2, -m_ResultImage.rect().height()/2);
//    //QGraphicsRectItem::setScale(factor);
//    update();
    setScaleX(factor);
    setScaleY(factor);
}

void ImageItem::setScaleX(qreal factor)
{
    //QSize s = m_Image.size();
    //QSize sc = m_Image.size() * factor;
    m_ScaleXY.setWidth(factor);
    int ss = std::max(m_Image.size().width() * m_ScaleXY.width() * 1, m_Image.size().height()* m_ScaleXY.height() * 1);

    QSize tempSize(ss, ss);
    m_ResultImage = QImage(tempSize, QImage::Format_ARGB32);
    setRect(-m_ConculusionImg.width()/2, -m_ConculusionImg.height()/2, m_ConculusionImg.width(), m_ConculusionImg.height());
    //setRect(-m_ResultImage.width(), -m_ResultImage.height(), m_ResultImage.width() * 2, m_ResultImage.height() * 2);
    //setTransformOriginPoint(-m_ResultImage.rect().width()/2, -m_ResultImage.rect().height()/2);
    //QGraphicsRectItem::setScale(factor);
    update();
}

void ImageItem::setScaleY(qreal factor)
{
    //QSize s = m_Image.size();
    //QSize sc = m_Image.size() * factor;
    m_ScaleXY.setHeight(factor);
    int ss = std::max(m_Image.size().width() * m_ScaleXY.width() * 1, m_Image.size().height()* m_ScaleXY.height() * 1);

    QSize tempSize(ss, ss);

    m_ResultImage = QImage(tempSize, QImage::Format_ARGB32);
    setRect(-m_ConculusionImg.width()/2, -m_ConculusionImg.height()/2, m_ConculusionImg.width(), m_ConculusionImg.height());
    //setRect(-m_ResultImage.width(), -m_ResultImage.height(), m_ResultImage.width() * 2, m_ResultImage.height() * 2);
    //setTransformOriginPoint(-m_ResultImage.rect().width()/2, -m_ResultImage.rect().height()/2);
    //QGraphicsRectItem::setScale(factor);
    update();
}

qreal ImageItem::scale () const
{
    return m_Scale;//(qreal)m_ConculusionImg.size().width() / m_Image.size().width();
}

QSizeF ImageItem::scaleXY () const
{
    return m_ScaleXY;//(qreal)m_ConculusionImg.size().width() / m_Image.size().width();
}


void ImageItem::setRotation ( qreal angle )
{
    QGraphicsRectItem::setRotation (angle);
    m_Angle = angle;
    update();
}

qreal ImageItem::rotation () const
{
    return m_Angle;
}

void ImageItem::setId(int id)
{
    m_Id = id;
}

int ImageItem::getId()
{
   return m_Id;
}

void ImageItem::paint( QPainter *p, const QStyleOptionGraphicsItem *option, QWidget * )
{
    QColor penColor = p->pen().color().lighter(150);
    QPen pen(penColor);
    pen.setStyle(Qt::DashLine);
    p->setPen(pen);
    QRect r(option->exposedRect.x(), option->exposedRect.y(), option->exposedRect.width(), option->exposedRect.height());
    QRect rr(-m_ConculusionImg.width()/2,-m_ConculusionImg.height()/2, m_ConculusionImg.rect().width(), m_ConculusionImg.rect().height());
    p->drawImage(rr, m_ConculusionImg, m_ConculusionImg.rect());
    //p->drawImage(QRectF(option->exposedRect.x() + m_ResultImage.width(), option->exposedRect.y() + m_ResultImage.height(), option->exposedRect.width(), option->exposedRect.height()), *m_SrcImage);
    if(this->isSelected() && g_SelRectVisible){
        //QRectF selRect(x(), y(), m_ConculusionImg.rect().width(), m_ConculusionImg.rect().height());
        p->drawRect(rr);
    }
}

void ImageItem::recalculateResult()
{
    //m_bEffDraw = true;
    init();
    QSize srcSize = m_Image.size();
    srcSize.setWidth(srcSize.width()*m_ScaleXY.width());
    srcSize.setHeight(srcSize.height()*m_ScaleXY.height());
    QImage destinationImage(srcSize * 1,QImage::Format_ARGB32_Premultiplied);
    destinationImage.fill(0);

    QImage fixedImage(m_ResultImage.size(), QImage::Format_ARGB32_Premultiplied);
    fixedImage.fill(0);
    m_ConculusionImg = QImage(srcSize, QImage::Format_ARGB32_Premultiplied);
    m_ConculusionImg.fill(0);
    QPainter painter2(&fixedImage);

    // print, fitting the viewport contents into a full page
    QRect r = /*this->rect();*/m_ResultImage.rect();
    QRect fr = /*this->rect();*/fixedImage.rect();
    int cy = y();
    int cx = x();
    QRect rr(x() - (fr.width()/2), y() - (fr.height()/2), fr.width(), fr.height());
    //QRectF rectScale(r.x(), r.y(), r.width() * scale(), r.height() * scale());
    // 배경 캡쳐
    if(scene()){
        scene()->render(&painter2, fixedImage.rect(), rr, Qt::KeepAspectRatioByExpanding);
    }
    painter2.setCompositionMode(QPainter::CompositionMode_Source);
    painter2.drawImage(QPoint(0, 0), fixedImage);

    painter2.setCompositionMode(QPainter::CompositionMode_SourceOver);
    painter2.drawImage(QPoint(0, 0), destinationImage);
    painter2.end();

    destinationImage = fixedImage;
    //m_ResultImage = destinationImage;

    QPainter::CompositionMode mode = (QPainter::CompositionMode)m_composition_mode;

    QPainter painterResult(&m_ResultImage);

    painterResult.setCompositionMode(QPainter::CompositionMode_Source);
    painterResult.fillRect(m_ResultImage.rect(), Qt::transparent);
    painterResult.setCompositionMode(QPainter::CompositionMode_SourceOver);

    painterResult.drawImage(0,0, destinationImage);
    painterResult.setCompositionMode(mode);
    if(m_SrcImage && m_SrcImage->isNull())
        m_SrcImage = NULL;

    //회전 축에의한 가감필요
    int rcx = 0.5 + (r.width()/2);
    int rcy = 0.5 + (r.height()/2);

    QRect test(0.5 + ((rect().width() - m_ConculusionImg.width())/2) , 0.5 + ((rect().height() - m_ConculusionImg.height())/2), m_ConculusionImg.width(), m_ConculusionImg.height());

    if(m_SrcImage){
        // 연산하여 1차이미지 그리기
        QMatrix matrix;
        matrix.translate(rcx, rcy);
        // 회전
        matrix.rotate(m_Angle);
        matrix.translate(-rcx, -rcy);
        painterResult.setMatrix(matrix);
        //
        painterResult.drawImage(test, m_Image, m_Image.rect());
        // 연산하여 2차이미지 그리기(회전값을 초기상태로)
        QMatrix matrix2;
        QImage backRotImg(m_ResultImage);
        matrix2.translate(rcx, rcy);
        // 회전 복귀
        matrix2.rotate(-m_Angle);
        matrix2.translate(-rcx, -rcy);
        painterResult.setMatrix(matrix2);
        m_ResultImage.fill(0);
        painterResult.drawImage(m_ResultImage.rect(), backRotImg, m_ResultImage.rect());
    }

    painterResult.setCompositionMode(QPainter::CompositionMode_DestinationOver);
    // 최종이미지
    QPainter painterCon(&m_ConculusionImg);
    // paint() 함수에서 쓸 이미지에 그린다 QGraphicsRectItem의 회전효과를 이용
    painterCon.drawImage(m_ConculusionImg.rect(), m_ResultImage, test);

    //painterResult.fillRect(m_ResultImage.rect(), Qt::white);
//    if(this->isSelected()){
//        QColor penColor = painterCon.pen().color().lighter(150);
//        QPen pen(penColor);
//        pen.setStyle(Qt::DashLine);
//        painterCon.setPen(pen);
//        painterCon.drawRect(QRectF(0, 0, m_ConculusionImg.width(), m_ConculusionImg.height()).adjusted(0, 0, 0, 0));
//        painterCon.end();
//    }
}

void ImageItem::update()
{
    // 로딩속도 현저한 감소
    if(m_bEffDraw){
        QGraphicsRectItem::update();
        recalculateResult();
        setRect(-m_ConculusionImg.width()/2, -m_ConculusionImg.height()/2, m_ConculusionImg.width(), m_ConculusionImg.height());
    }
}

void ImageItem::updateRect(qreal ax, qreal ay, qreal w, qreal h)
{
    //setRect(-m_ResultImage.width()/2, -m_ResultImage.height()/2, m_ResultImage.width(), m_ResultImage.height());
    setRect(0, 0, w, h);
}
